#include <gl/freeglut.h>

GLfloat ctrlPoints[4][3] =
{
    {-4,-4,0},{-2,3,0},
    {2,4.5,0},{3,-3,0}
};  // 控制点

void init()
{
    glShadeModel(GL_SMOOTH);
    glClearColor(1, 1, 1, 0);
    glShadeModel(GL_FLAT);
    // 定义曲线函数
    glMap1f(GL_MAP1_VERTEX_3, 0, 1, 3, 4, &ctrlPoints[0][0]);
    // void glMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat * points);
    // target参数指定了控制点表示什么。如表所示，并因此确定了points应该提供多少值
    // u1和u2参数表示变量u的变化范围，变量stride是每个存储块之间单精度或双精度浮点数的数量
    // order参数的值就是stride+1,它应该与控制点的数量一致
    // points参数指向第一个控制点的第一个坐标
    
    glEnable(GL_MAP1_VERTEX_3); // 激活
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    // 使用求值器按20等分计算Bezier曲线上的点
    glColor3f(0, 0, 0);
    glLineWidth(2);
    glBegin(GL_LINE_STRIP);
    for (int i = 0; i <= 100; i++)
        glEvalCoord1f((GLfloat)i/100);
    glEnd();

    // 绘制控制多边形
    glLineWidth(1);
    glColor3f(0, 0, 1);
    glBegin(GL_LINE_STRIP);
    for (int i = 0; i < 4; i++)
        glVertex3fv(&ctrlPoints[i][0]);
    glEnd();
    glFlush();
}

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (width <= height)
        glOrtho(-5, 5, -5 * (GLfloat)height / width,
            5 * (GLfloat)height / width, -5, 5);
    else
        glOrtho(-5 * (GLfloat)width / height, 5 * (GLfloat)width / height,
            -5, 5, -5, 5);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
    glutInitWindowSize(500, 500);
    glutCreateWindow("Bezier curve");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    
    glutMainLoop();
}